﻿using System.IO;
using Kotonoha.Server.Xml;

namespace Kotonoha.Server.Dictionaries.Kanjidic2 {
    [PluggableReader(DictionaryName = "Kanjidic2", FilePattern = "kanjidic2.xml")]
    public class Kanjidic2Reader : ICharDictionaryReader {
        private readonly XmlParser parser;
        private Kanjidic2 dic;
        private CharEntry chr;

        public Kanjidic2Reader() {
            parser = new XmlParser(createRootElement());
        }

        private ParentHandler createRootElement() {
            ParentHandler root = new ParentHandler("kanjidic2");
            root.Add(createHeaderHandler());
            root.Add(createCharHandler());
            root.OnStart += () => dic = new Kanjidic2(); 
            return root;
        }

        private ElementHandler createMiscHandler() {
            ParentHandler h = new ParentHandler("misc");
            h.Add(new ContentHandler("stroke_count", i => chr.Strokes = i));
            return h;
        }

        private ElementHandler createCharHandler() {
            ParentHandler ch = new ParentHandler("character");
            ch.OnStart += () => chr = new CharEntry();
            ch.OnEnd += () => dic.Add(chr.Writing, chr);
            ch.Add(new ContentHandler("literal", s => chr.Writing = s));
            ch.Add(createRM());
            ch.Add(createMiscHandler());
            return ch;
        }

        private ElementHandler createRM() {
            ParentHandler rm = new ParentHandler("reading_meaning");
            rm.Add(new ContentHandler("nanori", s => chr.addNanori(s)));
            ParentHandler group = new ParentHandler("rmgroup");
            group.Add(new AttributedHandler("reading", handleReading));
            group.Add(new AttributedHandler("meaning", handleMeaning));
            rm.Add(group);
            return rm;
        }

        private void handleMeaning(Element e) {
            string lang = e["m_lang"] ?? "en";
            if (lang == "en") {//TODO different languages
                chr.addMeaning(e.Content);
            }
        }

        private void handleReading(Element e) {
            string type = e["r_type"];
            switch(type) {
                case "ja_on":
                    chr.addOnyomi(e.Content);
                    break;
                case "ja_kun":
                    chr.addKunyomi(e.Content);
                    break;
            }
        }

        private ElementHandler createHeaderHandler() {
            ParentHandler header = new ParentHandler("header");
            header.Add(new ContentHandler("file_version", s => dic.Version = s));
            header.Add(new ContentHandler("database_version", s => dic.DatabaseCreation = s));
            header.Add(new ContentHandler("date_of_creation", s => dic.CreationDate = s));
            return header;
        }

        public ICharDictionary read(Stream stream) {
            parser.parse(stream);
            return dic;
        }
    }
}
